AWS Client VPN に接続したら名前解決ができなくなったのでカスタム DNS サーバーとは何かを調べ直してみた
コンバンハ、千葉(幸)です。
AWS Client VPN エンドポイントのパラメータの一つとして、カスタム DNS サーバー があります。明示的に設定しない限りはブランクである箇所なので、今まで特に気にせず過ごしてきました。
いろいろ設定を変えて検証する中で「名前解決できない!」という事態に陥り、ようやくその意味を調べることになりました。
今回はその内容についてまとめます。
ちなみに、私が引っかかったのは以下のようなケースです。
- クライアントのデフォルトの DNS 参照先はインターネット上のサーバ
- スプリットトンネル無効
- (すべてのクライアントトラフィックが Clinet VPN 経由になる)
- カスタム DNS サーバー未設定
- ターゲットネットワークはプライベートサブネット
ここでは、ターゲットネットワークの ENI からインターネット上の DNS サーバに対して到達できず、 DNS ルックアップが失敗するという事象でした。(実はそれだけではなかったのですが、、)
解決策とあわせてご紹介します。
目次
先にまとめ
- カスタム DNS サーバーを有効にすると、Client VPN 接続時に DNS パラメータがクライアントデバイスにプッシュされる
- DNS サーバへの経路が確立されているかを、クライアントデバイスのルートテーブルを意識して考慮しよう
- スプリットトンネル無効の場合デフォルトルートは Client VPN を向く
- スプリットトンネル有効の場合は Clinet VPN ルートテーブルの内容がデバイスにプッシュされる
- DNS サーバによっては接続元が制限されているので注意が必要
冒頭のケースについて補足
冒頭のケースの背景について、もう少し詳しく取りあげます。
なお、手元の環境は以下の通りです。
- クライアントデバイス:macOS Catalina 10.15.7
- VPN クライアント:AWS VPN Client 1.2.0
Client VPN 接続前
Client VPN に接続する前のクライアントデバイスの設定を確認します。 DNS サーバの参照先は以下の通りです。
- 218.xxx.xxx.xxx
- 220.xxx.xxx.xxx
macOS を使用しているため、/etc/resolv.conf
も確認しておきます。
% cat /etc/resolv.conf # # macOS Notice # # This file is not consulted for DNS hostname resolution, address # resolution, or the DNS query routing mechanism used by most # processes on this system. # # To view the DNS configuration used by this system, use: # scutil --dns # # SEE ALSO # dns-sd(1), scutil(8) # # This file is automatically generated. # domain xxx.xxx.xxx.ne.jp nameserver 218.xxx.xxx.xxx nameserver 220.xxx.xxx.xxx
名前解決を試みた際に、上記のサーバを参照していることが分かります。
% dig dev.classmethod.jp +identify +short 52.69.244.142 from server 218.xxx.xxx.xxx in 20 ms. 13.114.112.43 from server 218.xxx.xxx.xxx in 20 ms. 52.196.7.133 from server 218.xxx.xxx.xxx in 20 ms.
Client VPN 接続時(スプリットトンネル無効)
続いて、以下設定の Client VPN に接続します。
- スプリットトンネル無効
- カスタム DNS サーバー未設定
- ターゲットネットワークはプライベートサブネット
- インターネットへの経路を持たない
接続したことにより、クライアントデバイスのルートテーブルに変更が加わります。
% netstat -rn Routing tables Internet: Destination Gateway Flags Netif Expire 0/1 172.16.0.129 UGSc utun2 default 192.168.0.1 UGSc en0 18.177.246.62/32 192.168.0.1 UGSc en0 127 127.0.0.1 UCS lo0 127.0.0.1 127.0.0.1 UH lo0 128.0/1 172.16.0.129 UGSc utun2 169.254 link#6 UCS en0 ! 169.254.150.178 d4:6a:6a:5f:32:e7 UHLSW en0 ! 172.16.0.128/27 172.16.0.130 UGSc utun2 172.16.0.130 172.16.0.130 UH utun2 192.168.0 link#6 UCS en0 ! 192.168.0.1/32 link#6 UCS en0 ! 192.168.0.1 90:f3:5:ee:a2:bb UHLWIir en0 1136 192.168.0.14/32 link#6 UCS en0 ! 224.0.0/4 link#6 UmCS en0 ! 224.0.0.251 1:0:5e:0:0:fb UHmLWI en0 239.255.255.250 1:0:5e:7f:ff:fa UHmLWI en0 255.255.255.255/32 link#6 UCS en0 !
デフォルトルートが上書き( 0/1 および 128.0/1 宛ルートが追加)され、すべてのクライアントトラフィックが Client VPN トンネルを経由することになります。
このあたりの挙動は以下エントリでも取りあげましたのであわせてご参照ください。
一方で、参照先の DNS サーバには変更がありません。
% cat /etc/resolv.conf | grep nameserver nameserver 218.xxx.xxx.xxx nameserver 220.xxx.xxx.xxx
そのため、名前解決を試みると、デフォルトの DNS サーバを参照しに行きます。DNS ルックアップの通信は Client VPN エンドポイントを経由し、ターゲットネットワーク の ENI から宛先のサーバを目指しますが、今回のケースではインターネットに通信可能な状態でないため、名前解決に失敗します。
% dig dev.classmethod.jp +identify +short ; <<>> DiG 9.10.6 <<>> dev.classmethod.jp +identify +short ;; global options: +cmd ;; connection timed out; no servers could be reached
(なお、参照先として Amazon Provided DNS こと Route53 Resolver を明示的に指定すれば、問題なく名前解決はできます。)
% dig @10.0.0.2 dev.classmethod.jp +identify +short 52.196.7.133 from server 10.0.0.2 in 23 ms. 52.69.244.142 from server 10.0.0.2 in 23 ms. 13.114.112.43 from server 10.0.0.2 in 23 ms.
どう対応すればいいのか
今回のケースにおいて、問題なく名前解決が行えるようにするためにはどのように構成を変更すればよいでしょうか。
以下の 3 パターンで考えてみます。
- カスタム DNS サーバーを使用する
- ターゲットネットワークからインターネット疎通を可能にする
- スプリットトンネルを有効化する
パターン1. カスタム DNS サーバーを使用する
本エントリのメインテーマであるカスタム DNS サーバーを使用します。以下観点で、最も改修のインパクトが少なく済むパターンかと思います。
- VPC の構成を変更しない
- (パターン2. ではここが変わる)
- インターネット向けの経路を変更しない
- (パターン3. ではここが変わる)
カスタム DNS サーバーとして設定した値は、 VPN 接続時にクライアントにプッシュされます。先ほど手動で指定した Amazon Provided DNS を自動的に参照するように設定します。
Client VPN エンドポイントの変更画面より設定を行います。[ DNS サーバーを有効にする ] にチェックを入れ、指定する DNS サーバーの IP アドレスを入力します。
Amazon Provided DNS の IP アドレスは、VPC IPv4 ネットワークの範囲に 2 をプラスしたものです。
上記の変更が完了したのちに Client VPN に接続すると、参照先 DNS サーバが変更されていることが分かります。(本エントリでいちばん書きたかったところは実はここ)
% cat /etc/resolv.conf # # macOS Notice # # This file is not consulted for DNS hostname resolution, address # resolution, or the DNS query routing mechanism used by most # processes on this system. # # To view the DNS configuration used by this system, use: # scutil --dns # # SEE ALSO # dns-sd(1), scutil(8) # # This file is automatically generated. # search openvpn nameserver 10.0.0.2
名前解決を試みると、Amazon Provided DNS を参照して問題なく IP アドレスを引けました。
% dig dev.classmethod.jp +identify +short 13.114.112.43 from server 10.0.0.2 in 32 ms. 52.196.7.133 from server 10.0.0.2 in 32 ms. 52.69.244.142 from server 10.0.0.2 in 32 ms.
Amazon Provided DNS を参照先としている場合、VPC に関連づけられた Route 53 プライベートホストゾーンのレコードも引けます。
なお、当然ですが Client VPN との接続を切断すると参照先 DNS サーバーは元に戻ります。
パターン2. ターゲットネットワークからインターネット疎通を可能にする
カスタム DNS サーバーを使用せず、デフォルトの DNS 参照先に対しての通信経路を確保することで対応するパターンです。
結果から言うと、このパターンは失敗しました。私の環境では、もともと参照していた DNS サーバーが(おそらく)接続元を制限していたためです。
やろうとしたことは以下です。ターゲットネットワークの ENI から、インターネット上の DNS サーバにアクセス可能なように設定すれば問題なく名前解決できるだろうと考えていました。
結果的にダメだったですが、試行したことを載せておきます。
ターゲットネットワークで NAT Gateway 向けのルートを追加するか、パブリックサブネットに変更することでインターネットに出ていけるようになります。今回は NAT Gateway パターンで構成しました。
エンドポイントを以下条件に設定し直して、Client VPN に接続しました。
- カスタム DNS サーバー指定なし
- スプリットトンネル無効
カスタム DNS サーバーは設定していないため、参照先はデフォルトのままです。
% cat /etc/resolv.conf | grep nameserver nameserver 218.xxx.xxx.xxx nameserver 220.xxx.xxx.xxx
ここで名前解決を試みると、タイムアウトしてしまいます。
% dig dev.classmethod.jp +identify +short ; <<>> DiG 9.10.6 <<>> dev.classmethod.jp +identify +short ;; global options: +cmd ;; connection timed out; no servers could be reached
DNS サーバーへ到達できるかを確認します。 Ping による疎通確認は Client VPN 接続前の環境でも拒否されていたため、nc による確認を行いました。
Client VPN 接続前は以下のように接続が成功します。
% nc -v 218.xxx.xxx.xxx 53 -u Connection to 218.xxx.xxx.xxx port 53 [udp/domain] succeeded!
% nc -v 218.xxx.xxx.xxx 53 Connection to 218.xxx.xxx.xxx port 53 [tcp/domain] succeeded!
Client VPN に接続した後に同様のコマンドを実行すると、レスポンスが無いという結果になりました。そのため、通信が拒否されているのだと捉えました。
パブリック DNS である 8.8.8.8 や 1.1.1.1 を指定したところ問題なく名前解決ができます。インターネット上のリソースだから NG というわけではありません。
% dig @8.8.8.8 dev.classmethod.jp +identify +short 52.69.244.142 from server 8.8.8.8 in 25 ms. 13.114.112.43 from server 8.8.8.8 in 25 ms. 52.196.7.133 from server 8.8.8.8 in 25 ms.
% dig @1.1.1.1 dev.classmethod.jp +identify +short 52.69.244.142 from server 1.1.1.1 in 29 ms. 13.114.112.43 from server 1.1.1.1 in 29 ms. 52.196.7.133 from server 1.1.1.1 in 29 ms.
今回の環境でもともと参照していたのはプロバイダから提供された DNS サーバでした。DNS サーバによっては、リゾルバとしての接続を許可する送信元を限定しているでのはないか、と捉えています。
デフォルトの参照先を 8.8.8.8 や 1.1.1.1 に設定している環境であれば、このパターンで問題なく成功します。
パターン3. スプリットトンネルを有効化する
最後のパターンです。スプリットトンネルを有効化することで、VPN トンネルを経由せずに従来の DNS サーバ宛に通信が可能になります。
なお、DNS 宛の通信に限らず、インターネット向けの通信すべてが VPN トンネルを経由しなくなることに注意してください。この例では Client VPN ルートテーブルに 0.0.0.0/0 宛のルートが定義されていますが、そのルートはクライアントデバイスにプッシュされません。
Client VPN エンドポイントでスプリットトンネルを有効化し接続すると、クライアントデバイスのルートテーブルは以下のようになりました。変更が加わったのはハイライト部で、デフォルトルートは従来の物のままです。
% netstat -rn Routing tables Internet: Destination Gateway Flags Netif Expire default 192.168.0.1 UGSc en0 10/16 172.16.0.1 UGSc utun2 127 127.0.0.1 UCS lo0 127.0.0.1 127.0.0.1 UH lo0 169.254 link#6 UCS en0 ! 169.254.150.178 d4:6a:6a:5f:32:e7 UHLSW en0 ! 172.16/27 172.16.0.2 UGSc utun2 172.16.0.2 172.16.0.2 UH utun2 192.168.0 link#6 UCS en0 ! 192.168.0.1/32 link#6 UCS en0 ! 192.168.0.1 90:f3:5:ee:a2:bb UHLWIir en0 1145 192.168.0.14/32 link#6 UCS en0 ! 224.0.0/4 link#6 UmCS en0 ! 224.0.0.251 1:0:5e:0:0:fb UHmLWI en0 239.255.255.250 1:0:5e:7f:ff:fa UHmLWI en0 255.255.255.255/32 link#6 UCS en0 !
カスタム DNS サーバーを指定していないため、参照先は変わりません。
% cat /etc/resolv.conf | grep nameserver nameserver 218.xxx.xxx.xxx nameserver 220.xxx.xxx.xxx
もちろん名前解決は成功します。
% dig dev.classmethod.jp +identify +short 13.114.112.43 from server 218.xxx.xxx.xxx in 30 ms. 52.69.244.142 from server 218.xxx.xxx.xxx in 30 ms. 52.196.7.133 from server 218.xxx.xxx.xxx in 30 ms.
インターネットに接続する IP を確認すると、リモート環境で使用している物が返却されます。
% curl checkip.amazonaws.com/ 202.xx.xx.xxx
Client VPN 接続時にもクライアントデバイスから直接( VPN を経由せず)インターネットに通信してよい、というポリシーの環境であれば、スプリットトンネルを有効化したほうがシンプルに済みます。
終わりに
AWS Client VPN における名前解決およびカスタム DNS サーバーについてでした。
Client VPN 接続時にはカスタム DNS サーバーとして指定した IP がクライアントデバイスにプッシュされる。そのため、クライアントデバイスから DNS サーバーに対してきちんと疎通できる状態を意識する必要がある、ということを学びました。
実はパターン2. も成功する気マンマンでブログを書き始めていたので、やってみないとわからないことだらけだなぁというのを再認識しました。
以上、千葉(幸)がお送りしました。